x86: enable support for {rd,wr}{fs,gs}base instructions
authorKeir Fraser <keir@xen.org>
Sun, 24 Oct 2010 12:17:07 +0000 (13:17 +0100)
committerKeir Fraser <keir@xen.org>
Sun, 24 Oct 2010 12:17:07 +0000 (13:17 +0100)
... so that once in a while Xen knows of a new CPU feature before
Linux starts making use of it.

While (obviously) I wasn't able to test this, it seemed strait forward
enough to enable anyway.

Signed-off-by: Jan Beulich <jbeulich@novell.com>
xen/arch/x86/cpu/common.c
xen/arch/x86/domain.c
xen/arch/x86/traps.c
xen/include/asm-x86/cpufeature.h
xen/include/asm-x86/domain.h
xen/include/asm-x86/processor.h

index ebe96a2f0d6fe7a280cd50a12112e037d49ebe44..fb6d67c98340dc0141d9b9de5ad02eeafaad2e30 100644 (file)
@@ -311,6 +311,11 @@ void __cpuinit generic_identify(struct cpuinfo_x86 * c)
                        if ( xlvl >= 0x80000004 )
                                get_model_name(c); /* Default name */
                }
+
+               /* Intel-defined flags: level 0x00000007 */
+               if ( c->cpuid_level >= 0x00000007 )
+                       c->x86_capability[X86_FEATURE_FSGSBASE / 32]
+                               = cpuid_ebx(0x00000007);
        }
 
        early_intel_workaround(c);
index 9c5a7b5a97ce75e7fbadfefc683c298c1442329f..b67ddd6a00874d77ceb9899add75308ab4b629eb 100644 (file)
@@ -583,13 +583,15 @@ void arch_domain_destroy(struct domain *d)
     xfree(d->arch.irq_pirq);
 }
 
-unsigned long pv_guest_cr4_fixup(unsigned long guest_cr4)
+unsigned long pv_guest_cr4_fixup(const struct vcpu *v, unsigned long guest_cr4)
 {
     unsigned long hv_cr4_mask, hv_cr4 = real_cr4_to_pv_guest_cr4(read_cr4());
 
     hv_cr4_mask = ~X86_CR4_TSD;
     if ( cpu_has_de )
         hv_cr4_mask &= ~X86_CR4_DE;
+    if ( cpu_has_fsgsbase && !is_pv_32bit_domain(v->domain) )
+        hv_cr4_mask &= ~X86_CR4_FSGSBASE;
 
     if ( (guest_cr4 & hv_cr4_mask) != (hv_cr4 & hv_cr4_mask) )
         gdprintk(XENLOG_WARNING,
@@ -700,7 +702,7 @@ int arch_set_info_guest(
     v->arch.guest_context.user_regs.eflags |= X86_EFLAGS_IF;
 
     cr4 = v->arch.guest_context.ctrlreg[4];
-    v->arch.guest_context.ctrlreg[4] = cr4 ? pv_guest_cr4_fixup(cr4) :
+    v->arch.guest_context.ctrlreg[4] = cr4 ? pv_guest_cr4_fixup(v, cr4) :
         real_cr4_to_pv_guest_cr4(mmu_cr4_features);
 
     memset(v->arch.guest_context.debugreg, 0,
index e811f6257c147645d3bbd7a070a1e8ef1fc24467..fa3f48ebb8ce42200cff334b7b8d800a27f9bc23 100644 (file)
@@ -2176,7 +2176,7 @@ static int emulate_privileged_op(struct cpu_user_regs *regs)
             break;
 
         case 4: /* Write CR4 */
-            v->arch.guest_context.ctrlreg[4] = pv_guest_cr4_fixup(*reg);
+            v->arch.guest_context.ctrlreg[4] = pv_guest_cr4_fixup(v, *reg);
             write_cr4(pv_guest_cr4_to_real_cr4(v));
             break;
 
index 09d8307fca9e732f3016d710d082193dbff5a3c3..f9b42f8636dce29e6ecc83633b2bd82cf6a27c53 100644 (file)
@@ -9,7 +9,7 @@
 
 #include <xen/bitops.h>
 
-#define NCAPINTS       7       /* N 32-bit words worth of info */
+#define NCAPINTS       8       /* N 32-bit words worth of info */
 
 /* Intel-defined CPU features, CPUID level 0x00000001 (edx), word 0 */
 #define X86_FEATURE_FPU                (0*32+ 0) /* Onboard FPU */
 #define X86_FEATURE_SKINIT     (6*32+ 12) /* SKINIT, STGI/CLGI, DEV */
 #define X86_FEATURE_WDT                (6*32+ 13) /* Watchdog Timer */
 
+/* Intel-defined CPU features, CPUID level 0x00000007:0 (ebx), word 9 */
+#define X86_FEATURE_FSGSBASE   (7*32+ 0) /* {RD,WR}{FS,GS}BASE instructions */
+
 #define cpu_has(c, bit)                test_bit(bit, (c)->x86_capability)
 #define boot_cpu_has(bit)      test_bit(bit, boot_cpu_data.x86_capability)
 
 #define cpu_has_clflush                boot_cpu_has(X86_FEATURE_CLFLSH)
 #define cpu_has_page1gb                0
 #define cpu_has_efer           (boot_cpu_data.x86_capability[1] & 0x20100800)
+#define cpu_has_fsgsbase       0
 #else /* __x86_64__ */
 #define cpu_has_vme            0
 #define cpu_has_de             1
 #define cpu_has_clflush                boot_cpu_has(X86_FEATURE_CLFLSH)
 #define cpu_has_page1gb                boot_cpu_has(X86_FEATURE_PAGE1GB)
 #define cpu_has_efer           1
+#define cpu_has_fsgsbase       boot_cpu_has(X86_FEATURE_FSGSBASE)
 #endif
 
 #define cpu_has_ffxsr           ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) \
index 559a1deea1d479f2c167f4d2ed223504db46de85..7549126504575b348a3931dd0b6f4058d9bd8572 100644 (file)
@@ -429,7 +429,7 @@ void vcpu_show_execution_state(struct vcpu *);
 void vcpu_show_registers(const struct vcpu *);
 
 /* Clean up CR4 bits that are not under guest control. */
-unsigned long pv_guest_cr4_fixup(unsigned long guest_cr4);
+unsigned long pv_guest_cr4_fixup(const struct vcpu *, unsigned long guest_cr4);
 
 /* Convert between guest-visible and real CR4 values. */
 #define pv_guest_cr4_to_real_cr4(v)                         \
index 35efc68468208a020df17e164df54c18fa4cc342..7c24013cc202a03e8faa51aadf264aca461091bf 100644 (file)
@@ -83,6 +83,7 @@
 #define X86_CR4_OSXMMEXCPT     0x0400  /* enable unmasked SSE exceptions */
 #define X86_CR4_VMXE           0x2000  /* enable VMX */
 #define X86_CR4_SMXE           0x4000  /* enable SMX */
+#define X86_CR4_FSGSBASE       0x10000 /* enable {rd,wr}{fs,gs}base */
 #define X86_CR4_OSXSAVE        0x40000 /* enable XSAVE/XRSTOR */
 
 /*